package com.example.learn_vpn
import android.content.Intent
import android.net.VpnService
import android.os.Build
import android.util.Log
import androidx.annotation.RequiresApi
import com.example.learn_vpn.events.NetworkConfigChangedByUserEvent
import com.example.learn_vpn.events.NetworkListReplyEvent
import com.example.learn_vpn.events.NetworkListRequestEvent
import com.example.learn_vpn.events.NodeStatusEvent
import com.example.learn_vpn.events.NodeStatusRequestEvent
import com.example.learn_vpn.events.OrbitMoonEvent
import com.example.learn_vpn.events.PeerInfoReplyEvent
import com.example.learn_vpn.events.PeerInfoRequestEvent
import com.example.learn_vpn.events.StopEvent
import com.example.learn_vpn.events.VirtualNetworkConfigReplyEvent
import com.example.learn_vpn.events.VirtualNetworkConfigRequestEvent
import com.example.learn_vpn.model.MoonOrbit
import com.example.learn_vpn.model.Network
import com.example.learn_vpn.util.StringUtils
import com.google.gson.Gson
import com.zerotier.sdk.NodeStatus
import com.zerotier.sdk.Version
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.common.MethodChannel
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import java.math.BigInteger

class MainActivity: FlutterActivity(){
    private  var inten: Intent? = null
    val TAG = "emmmmmmmmm"
    private lateinit var network: Network
    private val REQ_VPNSERVICE: Int=1000001
    private val eventBus = EventBus.getDefault()
    @RequiresApi(Build.VERSION_CODES.LOLLIPOP)
    override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
        super.configureFlutterEngine(flutterEngine)
        MethodChannel(flutterEngine.dartExecutor.binaryMessenger,"learn_vpn").setMethodCallHandler { call, result ->
           runOnUiThread{
               when(call.method){
                   "startService"->{
                       val param = call.arguments as Map<*, *>
                       network=Gson().fromJson(param["data"]!! as String,Network::class.java)
                       Log.i(TAG, network.toString())
                       val intent=VpnService.prepare(this)
                       if(intent==null){
                           inten=Intent(this, ZeroTierOneService::class.java).putExtra(ZeroTierOneService.NETWORK_KEY,network)
                           startService(inten)
                       }else{
                           startActivityForResult(intent,REQ_VPNSERVICE)
                       }
                       result.success(true)
                   }
                   "stopService"->{
                       if(inten!=null) stopService(inten)
                       eventBus.post(StopEvent())
                       result.success(true)
                   }
                   "refreshList"->{
                       eventBus.post(NetworkListRequestEvent())
                       eventBus.post(NodeStatusRequestEvent())
                       result.success(true)
                   }
                   "getPeers"->{

                       // 更新入轨数据
                       eventBus.post(PeerInfoRequestEvent())
                       result.success(true);
                   }
                   "getVirtualNetworkConfig"->{
                       val param = call.arguments as Map<*, *>
                       eventBus.post(VirtualNetworkConfigRequestEvent(BigInteger( param["networkId"]!! as String,16).toLong()))
                   }
                   "changeNetwork"->{
                       val param = call.arguments as Map<*, *>
                       eventBus.post(NetworkConfigChangedByUserEvent(Gson().fromJson(param["data"]!! as String,Network::class.java)))
                       result.success(true)
                   }
                   "addOrbit"->{
                       //todo 触发事件入轨
                       val l: MutableList<MoonOrbit> = ArrayList()
//                       l.add(MoonOrbit())
                       eventBus.post(OrbitMoonEvent(l))
                       result.success(true)
                   }
               }
           }
        }
    }
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        when(requestCode){
            REQ_VPNSERVICE->{
                if (resultCode == -1) {
                    inten=Intent(this, ZeroTierOneService::class.java).putExtra(ZeroTierOneService.NETWORK_KEY,network)
                    startService(inten)
                }
            }
        }
    }
    override fun onDestroy() {
        super.onDestroy()
        if (this.eventBus.isRegistered(this)) {
            this.eventBus.unregister(this)
        }
    }


    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onNetworkListReply(event: NetworkListReplyEvent) {
        Log.d(TAG, "Got connecting network list")
        // 更新当前连接的网络
        val networks = event.networkList
        for (network in networks) {
            this.viewModel.doChangeConnectNetwork(network.nwid)
        }
        // 更新网络列表
        updateNetworkListAndNotify()
    }
    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onNodeStatus(event: NodeStatusEvent) {
        val status: NodeStatus = event.status
        val clientVersion: Version = event.clientVersion
        // 更新在线状态
        if (status.isOnline) {
            this.nodeStatusView.setText(R.string.status_online)
            if (this.nodeIdView != null) {
                this.nodeIdView.setText(java.lang.Long.toHexString(status.address))
            }
        } else {
            setOfflineState()
        }
        // 更新客户端版本
        if (this.nodeClientVersionView != null) {
            this.nodeClientVersionView.setText(StringUtils.toString(clientVersion))
        }
    }

    @Subscribe(threadMode = ThreadMode.BACKGROUND)
    fun onRequestPeerInfo(event: PeerInfoRequestEvent?) {
        if (this.node == null) {
            eventBus.post(PeerInfoReplyEvent(null))
            return
        }
        eventBus.post(PeerInfoReplyEvent(this.node.peers()))
    }

    @Subscribe(threadMode = ThreadMode.MAIN)
    fun onVirtualNetworkConfigReply(event: VirtualNetworkConfigReplyEvent) {
        val config = event.virtualNetworkConfig
        if (config == null) {
            Log.e(
                TAG,
                "Virtual network config not found!"
            )
            return
        }
        if (config.nwid !== this.networkId) {
            return
        }
        // 更新 LiveData
        this.virtualNetworkConfig.setValue(config)
        // 因为网络名称可能会变化，但 Network DAO 获取的对象会自动更新，所以需要主动触发一次更新
        val network: Network = network.getValue()
        this.network.setValue(network)
    }
}
